package require TclOO

# charmm command
# run MD simulation with changed configuration
oo::define Charmm  method run { setup {configuration {}}} {
    #save configuration, so that specific configuration do not override
#    foreach { key value } $configuration {
#    	puts "$key $value"
#	if [catch { set result [$setup getConf $key]} ] {set new(key) $value } else {set old($key) $result }
#    }
    $setup configure $configuration
    set cmd [$setup getCmd]
#    $setup configure [array get old]
#    $setup foregt [array names $new]
    return [my sendCmd $cmd]
}
# complete crashed simulation
oo::define Charmm method complete { setup  {configuration {}}} {}
# continue simulation with new simulation
oo::define Charmm method continue { setup1 with setup2  { configuration {}}} {
    set conf(continueFile) [$setup1 getConf restartFile]
    array set conf $configuration
    puts [array get conf]
    my run $setup2 [array get conf] 
}
# redo simulation with same setup 
oo::define Charmm method redo { setup {configuration {}}} {}



#MD setup
oo::class create MD {
    variable par
    constructor { {parameters {} }} {
	    my variable par
    	array set par {
	        integrator verlet
	    }
	    my configure $parameters 
    }
    method configure {} {}
    method getConf { parameter } {
    	my variable par
    	return $par($parameter)
    }
    method getLastStep {} {
    }
    method getCmd {} {
    }
    method copyto { destiny { parameters {} } } {
	my variable par
	MD create $destiny
	$destiny configure [array get par]
	$destiny configure $parameters
    }
}
oo::define MD method configure { parameters } {
    my variable par
    set parameters [subst $parameters]
    array set par $parameters
}
oo::define MD method forget { parameters } {
    my variable par
    array unset par $parameters
}
oo::define MD method getCmd {} {
    my variable par
    if { $par(langevin) == on } { 
        set cmd "scalar fbeta set $par(langevinFriction)\n" 
	    set par(integrator) langevin
    } else {
	    set cmd ""
	    set par(integrator) verlet
    }
    if { $par(timestep) > 1 } { append cmd "shake bonh param tol 1.0e-6\n" }
    if [info exists par(restartFile)] { append cmd "open write unit 52 card name $par(restartFile)\n" }
    if [info exists par(dcdFile)] { append cmd "open write unit 53 file name $par(dcdFile)\n" 
    }
    if [info exists par(continueFile) ] { append cmd "open read unit 51 card name $par(continueFile)\n" 
	append cmd "dynamic restart $par(integrator) nstep $par(numsteps) timestep [ expr 0.001*$par(timestep)] -\n"
	append cmd "IUNREA 51 - \n" 
    } else { append cmd "dynamic start $par(integrator) nstep $par(numsteps) timestep [expr 0.001*$par(timestep)] - \n"
            append cmd " iseed $par(seed)  - \n"
    }
    append cmd " INBFrq $par(nbondedFreq) - \n"
    append cmd " NSAVC $par(saveFreq) NPRINT $par(printFreq) -\n"
    append cmd " IUNWRI 52 IUNCRD 53 - \n"
    append cmd " IPRFrq [expr 10*$par(printFreq)] - \n"
    append cmd " First $par(initTemp) Finalt $par(temperature) Teminc $par(deltaTemp) Tbath $par(temperature) Twindh 5.0 Twindl 5.0 IHTFREQ $par(heatFreq)  \n" 
    append cmd "close unit 52\n close unit 53 \n"
    if [info exists par(continueFile) ] { append cmd "close unit 51\n" }
    return $cmd
}
